<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  <link rel="shortcut icon" href="../img/favicon.ico" type="image/x-icon">
  <link rel="stylesheet" href="../css/style.css">
  <title>patch</title>
</head>
<body>
  <img src="../img/patch-1.png" alt="" style="margin: 0 auto; display: block">
  <img src="../img/patch-old-new-children.png" alt="">
  <h2>Ⅰ patch介绍</h2>
  <h3>简介</h3>
  <li>
    DOM操作远远比不上Javascript运行的快。patch的本质其实是<span>使用Javascript的运算成本来替换DOM操作的执行成本</span>
  </li>
  <li>
    patch的目的是<span>修改DOM节点</span>。也可以理解为渲染视图。patchVNode方法里就是执行了一些新增、设置文本节点、删除等的操作
  </li>
  <li>
    Vuejs的更新可能会做三件事：1.创建新增的节点； 2.删除已经废弃的节点； 3.如果发现已有节点的位置不同，会进行移位<span>(for循环中，如果当前VNode是需要移位的。那么未循环到元素(未循环到的元素即当前元素之后的元素)之前的哪个位置，就是需要移位的位置)</span>；
  </li>
  <li>
    渲染视图的标准是新的VNode，而不是老的VNode。
  </li>

  <h3>新增节点</h3>
  <li>
    当因为状态改变而新增的节点在DOM中不存在时，我们才需要创建一个节点并插入到DOM中，通常发生在首频渲染。调用的方法是当前环境下的creatEle
  </li>
  
  <h3>删除节点</h3>
  <li>
    当new VNode与old VNode完全不是一个节点时，得知新的VNode就是一个全新的节点，而oldVNode时一个需要被废弃的节点。调用remove, insert。或者虽然是同一个节点，但是新节点中不存在某个子节点，旧的VNode中存在，就remove掉旧VNode中的这个子节点
  </li>

  <h3>
    更详细的对比-移位
  </h3>
  <li>
    当两个VNode时同一个节点时，需要进行更详细的分析对比，通常要分析两个VNode的子节点。子节点通长会发生移位。
  </li>

  <h2>Ⅱ 创建节点</h2>
  <h3>创建节点</h3>
  <li>
    创建节点通常要同时创建他们的子节点，创建子节点是一个<span>递归</span>的过程。VNode中的children属性保存了当前节点的所有子虚拟节点。所以只需要将每个子虚拟节点循环执行一遍创建元素的逻辑旧可以了
  </li>
  <li>
    只有三种类型的节点或被创建并插入到DOM中：元素节点，注释节点，文本节点
  </li>

  <h2>Ⅲ 删除节点</h2>
  <li>
    封装方法中，removeNode用于删除视图中的单个节点，而removeVnodes用于删除一组指定的节点
  </li>

  <h2>Ⅳ 更新节点</h2>
  <li>
    1.静态节点不会随状态变化，不需要更新
  </li>
  <li>
    2. new VNode（新虚拟节点）有text属性，那么直接用new VNode的text为参数调用setTextContent方法。忽略old VNode
  </li>
  <li>
    3. 新虚拟节点无text属性：
    <ul class="incent">
      <li>
        new VNode有children: 同时old VNode也有children，<b>此时需要进行对比两个VNode的子节点</b> 。如果old VNode中没有children，用new VNode的children插入到视图（形成DOM）
      </li>
      <li>
        new VNode没有children：既不是文本节点也没有children属性，说明是一个空的标签。这时候旧的虚拟节点中有子节点，需要删除，有什么删除什么，最终达到空标签的目的
      </li>
    </ul>
  </li>

  <h2>Ⅴ 当new VNode与old VNode都有children时：<em>更新子节点</em></h2>
  <li>
    更新的前提是循环，<span>循环new VNode，寻找old VNode中与之对应的节点</span>
  </li>

  <h2>Ⅵ 优化策略</h2>
  <li>
    由于Vue存在的优化策略，所以在循环的时候，并不是从前向后，而是从两端到中间。开始位置被处理后，开始位置与结束位置的指针就各自向中间移动一个位置
  </li>
  <li>
    new VNode先循环完，说明后剩下的old VNode节点都是需要废弃的。
  </li>
  <li>
    old VNode先循环完，说明new VNode中剩下的都是需要新增的。
  </li>
  <li>
    这种循环方式减少了循环次数，增加了性能
  </li>
</body>
</html>